import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * En esta clase esta todo lo relacionado al juego, desde su implementación básica de la creación de los objetos base hasta el incemento o decremento de vidas, niveles
 * etc.
 * 
 * @author Ulises Yamil Castorena Caldera 
 * @version 1.0
 */
public class Mundo extends World
{
    private int nivel; //Variable utilizada para saber el nivel en que se encuentra.
    private boolean band;  //Bandera que indica si el juego se necesita inicializar.
    private Vidas vid; //Objeto de la clase Vidas que indica las vidas.    
    private Tiempo tiem; //Objecto de la clase tiempo que indica el tiempo restante.
    private Numero num;//Objeto de la clase Numero que indica los metros restantes.
    private boolean band2;  //Variable que indica en que momento se añade un reloj al mundo
    private boolean primer; //Variable que indica en que momento se debe de enviar un perro.
    private int prim; //Variable que indica que el proceso de selección del menu esta terminado.
    private boolean pier;  //Variable que indica que todas las vidas se terminaron y el juego debe detenerse.
    
    /**
     * Constructor de la clase Mundo, inicializa los valores de las variables. 
     */
    public Mundo()
    {    
        super(800, 400, 1);       
        nivel = 1;        
        pier = false;
        band = false;
        band2 = false;
        primer = false;
    }    
    
    /**
     * Método que realiza el actua del mundo, en el se inicializan los mundos y se crean dependiendo del nivel en el que esta.
     */    
    public void act()
    {        
        if(prim == 0)
           menu();
        else if(prim == 2)
        {
           if(!band)
              inicializa();
            else if(nivel == 1)
            {
                nivel1();
                enviaPrimero();
            }
            else if(nivel == 2)
            {
                nivel2();
                enviaPrimero();
            }
            else if(nivel == 3)
            {
                nivel3();
                enviaPrimero();
            }
        }
    }
    
    /**
     * Método que es utilizado para el menu, es el primer método en llamar.
     */
    public void menu()
    {
        addObject(new Portada(),400,200);
        addObject(new LetraPort(),566,225);    
        addObject(new LetraAy(false),624,293);
        addObject(new LetraCre(),666,353);
        prim = 1;
    }
    
    /**
     * Método que añade los objetos enemigos, pero solo del nivel uno.
     */
    public void nivel1()
    {           
        if(band2)
        {
           if(Greenfoot.getRandomNumber(2) == 1)
           {
              addObject(new Reloj(),799,Greenfoot.getRandomNumber(260) + 64);
              band2 = false;
           }
        }
    }
    
    /**
     * Método que añade los objetos enemigos, pero solo del nivel dos.
     */
    public void nivel2()
    {
        if(Greenfoot.getRandomNumber(100) == 0)
        {
            if(Greenfoot.getRandomNumber(10) == 0)
            {
               if(Greenfoot.getRandomNumber(2) == 0)
                  addObject(new Perro(false),799,336);
               else
                  addObject(new Perro(true),799,64);
            }
            else if(Greenfoot.getRandomNumber(10) == 1)
            {
               if(Greenfoot.getRandomNumber(2) == 0)            
                  addObject(new Persona(false),799,317);
               else
                  addObject(new Persona(true),799,83);            
            }
        }    
        if(band2)
        {
           if(Greenfoot.getRandomNumber(100) == 1)
           {
              addObject(new Reloj(),799,Greenfoot.getRandomNumber(260) + 64);
              band2 = false;
           }
        }
    }
    
    /**
     * Método que añade los objetos enemigos, pero solo del nivel dos.
     */
    public void nivel3()
    {
        if(Greenfoot.getRandomNumber(100) == 0)
        {
            if(Greenfoot.getRandomNumber(2) == 0)
            {
               if(Greenfoot.getRandomNumber(2) == 0)
                  addObject(new Perro(false),799,336);
               else
                  addObject(new Perro(true),799,64);
            }
            else
            {
               if(Greenfoot.getRandomNumber(2) == 0)            
                  addObject(new Persona(false),799,317);
               else
                  addObject(new Persona(true),799,83);            
            }
        }      
    }
    
    /**
     * Método que incrementa el nivel.
     */
    public void incrementaNivel()
    {
        nivel ++;       
        if(nivel == 4)
        {
            removeObjects(getObjects(null));    
            addObject(new Textos(2),400,200);
            Greenfoot.delay(100);
            removeObjects(getObjects(Textos.class));
            Greenfoot.stop();
        }
        addObject(new Textos(1),400,200);
        Greenfoot.delay(100);        
        removeObjects(getObjects(null));
        band = false;
    }
    
    /**
     * Método que inicializa y añade todos lo objetos necesarios para el juego.
     */
    public void inicializa()
    {
        addObject(new Barra(),super.getHeight(),20);
        addObject(new Barra(),super.getHeight(),380);
        addObject(new Personaje(),98,332);
        addObject(new Letra("Tiempo"),30,70);
        addObject(new Letra("Metros"),30,110);
        addObject(new Letra("Vidas"),30,150);
        addObject(new Letra(nivel),super.getHeight(),20);
        addObject(new Numero(),35,130);
        vid = new Vidas();
        addObject(vid,35,170);      
        tiem = new Tiempo();
        addObject(tiem,35,90);
        band = true;
    }
    
    /**
     * Remueve los objetos inicesarios para despues volverlos a intoduccir. 
     */
    public void pierdeVida()
    {      
        addObject(new Textos(0),400,200);
        Greenfoot.delay(100);
        removeObjects(getObjects(Personaje.class));
        removeObjects(getObjects(Textos.class));
        removeObjects(getObjects(Reloj.class));
        removeObjects(getObjects(Enemigo.class));
        removeObjects(getObjects(Numero.class));
        vid.disminuyeVida();        
        if(!pier)
           reset();
        else 
           Greenfoot.stop();
    }
    
    /**
     * Remueve los objetos inicesarios para despues volverlos a intoduccir.     
     */
    public void pierdeVida2()
    {        
        addObject(new Textos(0),400,200);
        Greenfoot.delay(100);
        removeObjects(getObjects(Personaje.class));
        removeObjects(getObjects(Textos.class));
        removeObjects(getObjects(Enemigo.class));
        removeObjects(getObjects(Reloj.class));
        removeObjects(getObjects(Numero.class));
        vid.disminuyeVida();
        tiem.pierdeTiempo();
        if(!pier)
           reset();
        else 
           Greenfoot.stop();
    }
    
    /**
     * Reinicia la ubicación de el usuario y del numero de metros faltantes.
     */
    public void reset()
    {
        addObject(new Personaje(),98,332);
        addObject(new Numero(),35,130);
        primer = false;
    }      
    
    /**
     * El método es llamado para saber si el reloj a llegado al limite de la pantalla ya así poder enviar otro.
     */
    public void mandaTiempo()
    {
        band2 = true;
    }
    
    /**
     * Envia por primera vez un objeto de la clase reloj, para asi poder iniciar.
     */
    public void enviaPrimero()
    {
        if(!primer)
        {
           addObject(new Reloj(),799,Greenfoot.getRandomNumber(260) + 64);
           addObject(new Perro(false),799,336);
           primer = true;
        }
    }
    
    /**
     * Método que manda un mensaje al reloj para incrementarlo.
     */
    public void incrementa()
    {
        tiem.incrementaTiempo();
    }
    
    /**
     * Método que crea un objeto de tipo Policia y lo añade al mundo.
     * @param valor Indica si el objeto se añade en la parte superior o inferior.
     */
    public void mandaPolicia(boolean valor)    
    {
        if(!valor)        
           addObject(new Policia(valor),799,301);
        else
           addObject(new Policia(valor),799,100);
    }
    
    /**
     * Método que indica que el juego ya esta inicializado y es posible comenzar.
     */
    public void comiezaJuego()
    {
        removeObjects(getObjects(null));
        prim = 2;
    }
    
    /**
     * Método que es llamado cuando alguna condicion para perder se cumple.
     */
    public void pierdes()
    {
        removeObjects(getObjects(null));
        addObject(new Textos(3),400,200);
        Greenfoot.delay(100);    
        pier = true;        
    }
    
    /**
     * Método que crea un objeto de tipo Perro y lo añade al mundo.
     */
    public void enviaPerro()
    {
        if(Greenfoot.getRandomNumber(2) == 0)
           addObject(new Perro(false),799,336);
        else
           addObject(new Perro(true),799,64);
    }     
}
